package org.jks.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;

import org.jks.constant.SysConfig;
import org.jks.response.model.UIFile;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

public class FileUtil {
	public static Map<String, String> contentTypes = new HashMap<String, String>();
	static {
		contentTypes.put("ez", "application/andrew-inset");
		contentTypes.put("hqx", "application/mac-binhex40");
		contentTypes.put("cpt", "application/mac-compactpro");
		contentTypes.put("mathml", "application/mathml+xml");
		contentTypes.put("doc", "application/msword");
		contentTypes.put("bin", "application/octet-stream");
		contentTypes.put("dms", "application/octet-stream");
		contentTypes.put("lha", "application/octet-stream");
		contentTypes.put("lzh", "application/octet-stream");
		contentTypes.put("exe", "application/octet-stream");
		contentTypes.put("class", "application/octet-stream");
		contentTypes.put("so", "application/octet-stream");
		contentTypes.put("dll", "application/octet-stream");
		contentTypes.put("csv", "application/octet-stream");
		contentTypes.put("oda", "application/oda");
		contentTypes.put("ogg", "application/ogg");
		contentTypes.put("pdf", "application/pdf");
		contentTypes.put("ai", "application/postscript");
		contentTypes.put("eps", "application/postscript");
		contentTypes.put("ps", "application/postscript");
		contentTypes.put("rdf", "application/rdf+xml");
		contentTypes.put("smi", "application/smil");
		contentTypes.put("smil", "application/smil");
		contentTypes.put("gram", "application/srgs");
		contentTypes.put("grxml", "application/srgs+xml");
		contentTypes.put("mif", "application/vnd.mif");
		contentTypes.put("xul", "application/vnd.mozilla.xul+xml");
		contentTypes.put("xls", "application/vnd.ms-excel");
		contentTypes.put("ppt", "application/vnd.ms-powerpoint");
		contentTypes.put("wbxml", "application/vnd.wap.wbxml");
		contentTypes.put("wmlc", "application/vnd.wap.wmlc");
		contentTypes.put("wmlsc", "application/vnd.wap.wmlscriptc");
		contentTypes.put("vxml", "application/voicexml+xml");
		contentTypes.put("bcpio", "application/x-bcpio");
		contentTypes.put("vcd", "application/x-cdlink");
		contentTypes.put("pgn", "application/x-chess-pgn");
		contentTypes.put("cpio", "application/x-cpio");
		contentTypes.put("csh", "application/x-csh");
		contentTypes.put("dcr", "application/x-director");
		contentTypes.put("dir", "application/x-director");
		contentTypes.put("dxr", "application/x-director");
		contentTypes.put("dvi", "application/x-dvi");
		contentTypes.put("spl", "application/x-futuresplash");
		contentTypes.put("gtar", "application/x-gtar");
		contentTypes.put("hdf", "application/x-hdf");
		contentTypes.put("php", "application/x-httpd-php");
		contentTypes.put("php4", "application/x-httpd-php");
		contentTypes.put("php3", "application/x-httpd-php");
		contentTypes.put("phtml", "application/x-httpd-php");
		contentTypes.put("phps", "application/x-httpd-php-source");
		contentTypes.put("js", "application/x-javascript");
		contentTypes.put("skp", "application/x-koan");
		contentTypes.put("skd", "application/x-koan");
		contentTypes.put("skt", "application/x-koan");
		contentTypes.put("skm", "application/x-koan");
		contentTypes.put("latex", "application/x-latex");
		contentTypes.put("nc", "application/x-netcdf");
		contentTypes.put("cdf", "application/x-netcdf");
		contentTypes.put("crl", "application/x-pkcs7-crl");
		contentTypes.put("sh", "application/x-sh");
		contentTypes.put("shar", "application/x-shar");
		contentTypes.put("swf", "application/x-shockwave-flash");
		contentTypes.put("sit", "application/x-stuffit");
		contentTypes.put("sv4cpio", "application/x-sv4cpio");
		contentTypes.put("sv4crc", "application/x-sv4crc");
		contentTypes.put("tgz", "application/x-tar");
		contentTypes.put("tar", "application/x-tar");
		contentTypes.put("tcl", "application/x-tcl");
		contentTypes.put("tex", "application/x-tex");
		contentTypes.put("texinfo", "application/x-texinfo");
		contentTypes.put("texi", "application/x-texinfo");
		contentTypes.put("t", "application/x-troff");
		contentTypes.put("tr", "application/x-troff");
		contentTypes.put("roff", "application/x-troff");
		contentTypes.put("man", "application/x-troff-man");
		contentTypes.put("me", "application/x-troff-me");
		contentTypes.put("ms", "application/x-troff-ms");
		contentTypes.put("ustar", "application/x-ustar");
		contentTypes.put("src", "application/x-wais-source");
		contentTypes.put("crt", "application/x-x509-ca-cert");
		contentTypes.put("xhtml", "application/xhtml+xml");
		contentTypes.put("xht", "application/xhtml+xml");
		contentTypes.put("xml", "application/xml");
		contentTypes.put("xsl", "application/xml");
		contentTypes.put("dtd", "application/xml-dtd");
		contentTypes.put("xslt", "application/xslt+xml");
		contentTypes.put("zip", "application/zip");
		contentTypes.put("au", "audio/basic");
		contentTypes.put("snd", "audio/basic");
		contentTypes.put("mid", "audio/midi");
		contentTypes.put("midi", "audio/midi");
		contentTypes.put("kar", "audio/midi");
		contentTypes.put("mpga", "audio/mpeg");
		contentTypes.put("mp2", "audio/mpeg");
		contentTypes.put("mp3", "audio/mpeg");
		contentTypes.put("mp4", "video/mp4");
		contentTypes.put("aif", "audio/x-aiff");
		contentTypes.put("aiff", "audio/x-aiff");
		contentTypes.put("aifc", "audio/x-aiff");
		contentTypes.put("m3u", "audio/x-mpegurl");
		contentTypes.put("ram", "audio/x-pn-realaudio");
		contentTypes.put("rm", "audio/x-pn-realaudio");
		contentTypes.put("rpm", "audio/x-pn-realaudio-plugin");
		contentTypes.put("ra", "audio/x-realaudio");
		contentTypes.put("wav", "audio/x-wav");
		contentTypes.put("pdb", "chemical/x-pdb");
		contentTypes.put("xyz", "chemical/x-xyz");
		contentTypes.put("bmp", "image/bmp");
		contentTypes.put("cgm", "image/cgm");
		contentTypes.put("gif", "image/gif");
		contentTypes.put("ief", "image/ief");
		contentTypes.put("jpeg", "image/jpeg");
		contentTypes.put("jpg", "image/jpeg");
		contentTypes.put("jpe", "image/jpeg");
		contentTypes.put("png", "image/png");
		contentTypes.put("svg", "image/svg+xml");
		contentTypes.put("tiff", "image/tiff");
		contentTypes.put("tif", "image/tiff");
		contentTypes.put("djvu", "image/vnd.djvu");
		contentTypes.put("djv", "image/vnd.djvu");
		contentTypes.put("wbmp", "image/vnd.wap.wbmp");
		contentTypes.put("ras", "image/x-cmu-raster");
		contentTypes.put("ico", "image/x-icon");
		contentTypes.put("pnm", "image/x-portable-anymap");
		contentTypes.put("pbm", "image/x-portable-bitmap");
		contentTypes.put("pgm", "image/x-portable-graymap");
		contentTypes.put("ppm", "image/x-portable-pixmap");
		contentTypes.put("rgb", "image/x-rgb");
		contentTypes.put("xbm", "image/x-xbitmap");
		contentTypes.put("xpm", "image/x-xpixmap");
		contentTypes.put("xwd", "image/x-xwindowdump");
		contentTypes.put("igs", "model/iges");
		contentTypes.put("iges", "model/iges");
		contentTypes.put("msh", "model/mesh");
		contentTypes.put("mesh", "model/mesh");
		contentTypes.put("silo", "model/mesh");
		contentTypes.put("wrl", "model/vrml");
		contentTypes.put("vrml", "model/vrml");
		contentTypes.put("ics", "text/calendar");
		contentTypes.put("ifb", "text/calendar");
		contentTypes.put("css", "text/css");
		contentTypes.put("shtml", "text/html");
		contentTypes.put("html", "text/html");
		contentTypes.put("htm", "text/html");
		contentTypes.put("asc", "text/plain");
		contentTypes.put("txt", "text/plain");
		contentTypes.put("rtx", "text/richtext");
		contentTypes.put("rtf", "text/rtf");
		contentTypes.put("sgml", "text/sgml");
		contentTypes.put("sgm", "text/sgml");
		contentTypes.put("tsv", "text/tab-separated-values");
		contentTypes.put("wml", "text/vnd.wap.wml");
		contentTypes.put("wmls", "text/vnd.wap.wmlscript");
		contentTypes.put("etx", "text/x-setext");
		contentTypes.put("mpeg", "video/mpeg");
		contentTypes.put("mpg", "video/mpeg");
		contentTypes.put("mpe", "video/mpeg");
		contentTypes.put("qt", "video/quicktime");
		contentTypes.put("mov", "video/quicktime");
		contentTypes.put("mxu", "video/vnd.mpegurl");
		contentTypes.put("avi", "video/x-msvideo");
		contentTypes.put("movie", "video/x-sgi-movie");
		contentTypes.put("ice", "x-conference/x-cooltalk");
		contentTypes
				.put("docx",
						"application/vnd.openxmlformats-officedocument.wordprocessingml.document");
		contentTypes
				.put("dotx",
						"application/vnd.openxmlformats-officedocument.wordprocessingml.template");
		contentTypes
				.put("pptx",
						"application/vnd.openxmlformats-officedocument.presentationml.presentation");
		contentTypes
				.put("ppsx",
						"application/vnd.openxmlformats-officedocument.presentationml.slideshow");
		contentTypes
				.put("potx",
						"application/vnd.openxmlformats-officedocument.presentationml.template");
		contentTypes
				.put("xlsx",
						"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
		contentTypes
				.put("xltx",
						"application/vnd.openxmlformats-officedocument.spreadsheetml.template");
	}

	public static void moveFile(ServletContext servletContext,
			String sourcePath, String targetPath, boolean isRandom,
			String filename) {
		String basePath = servletContext.getRealPath("/");
		String removePath = basePath + File.separator + sourcePath;
		copyFile(servletContext, sourcePath, targetPath, isRandom, filename);
		File file = new File(removePath);
		file.delete();
	}

	public static void copyFile(MultipartFile file, String path) {
		if (path == null || path.length() == 0) {
			return;
		}
		String basePath = path.substring(0, path.lastIndexOf(File.separator));
		File folder = new File(basePath);
		if (!folder.exists()) {
			folder.mkdirs();
		}
		InputStream inputStream = null;
		OutputStream outputStream = null;
		try {
			inputStream = file.getInputStream();
			outputStream = new FileOutputStream(path);
			int readBytes = 0;
			byte[] buffer = new byte[10000];
			while ((readBytes = inputStream.read(buffer, 0, 10000)) != -1) {
				outputStream.write(buffer, 0, readBytes);
			}
			outputStream.close();
			inputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void copyFile(File sourceFile, File targetFile){
		BufferedInputStream inBuff = null;
		BufferedOutputStream outBuff = null;
		try {
			inBuff = new BufferedInputStream(new FileInputStream(sourceFile));
			outBuff = new BufferedOutputStream(new FileOutputStream(targetFile));
			byte[] b = new byte[1024 * 5];
			int len;
			while ((len = inBuff.read(b)) != -1) {
				outBuff.write(b, 0, len);
			}
			outBuff.flush();
		} 
		catch(Exception e){
			e.printStackTrace();
		}
		finally {
			if (inBuff != null){
				try{
					inBuff.close();
				}
				catch(Exception e){
					e.printStackTrace();
				}
			}
			if (outBuff != null){
				try{
					outBuff.close();
				}
				catch(Exception e){
					e.printStackTrace();
				}
			}
		}
	}

	public static void copyFile(ServletContext servletContext,
			String sourcePath, String targetPath, boolean isRandom,
			String filename) {
		String basePath = servletContext.getRealPath("/");
		sourcePath = basePath + File.separator + sourcePath;
		if (!isRandom) {
			targetPath = basePath + File.separator
					+ getTargetPath(sourcePath, targetPath);
		} else {
			targetPath = basePath + File.separator + targetPath
					+ File.separator + filename;
		}
		String copyFilePath = targetPath.substring(0,
				targetPath.lastIndexOf(File.separator));
		if (copyFilePath != null && copyFilePath.length() != 0) {
			File file = new File(copyFilePath);
			if (!file.exists()) {
				file.mkdirs();
			}
		}

		try {
			InputStream inputStream = new FileInputStream(sourcePath);
			OutputStream outputStream = new FileOutputStream(targetPath);
			int readBytes = 0;
			byte[] buffer = new byte[10000];
			while ((readBytes = inputStream.read(buffer, 0, 10000)) != -1) {
				outputStream.write(buffer, 0, readBytes);
			}
			outputStream.close();
			inputStream.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static String getFilename(String path) {
		return path.substring(path.lastIndexOf(File.separator) + 1);
	}

	public static String getExtension(String path) {
		return path.substring(path.lastIndexOf(".") + 1);
	}

	public static String getTargetPath(String sourcePath, String targetPath) {
		return SysConfig.ATTACHEMENT + File.separator + SysConfig.MATERIAL
				+ File.separator + targetPath + File.separator
				+ getFilename(sourcePath);
	}

	public static void uploadFile(ServletContext servletContext,
			MultipartFile file) {
		String filepath = servletContext.getRealPath("/") + File.separatorChar
				+ SysConfig.UPLOAD + File.separatorChar;
		uploadFile(servletContext, file, filepath);
	}

	public static void uploadFile(ServletContext servletContext, String path,
			MultipartFile file) {
		String filepath = servletContext.getRealPath("/") + File.separatorChar
				+ path + File.separatorChar;
		uploadFile(servletContext, file, filepath);
	}

	public static void uploadFile(ServletContext servletContext,
			MultipartFile file, String targetPath) {
		InputStream inputStream = null;
		OutputStream outputStream = null;
		String filename = targetPath + file.getOriginalFilename();
		try {
			inputStream = file.getInputStream();
			outputStream = new FileOutputStream(filename);
			int readBytes = 0;
			byte[] buffer = new byte[10000];
			while ((readBytes = inputStream.read(buffer, 0, 10000)) != -1) {
				outputStream.write(buffer, 0, readBytes);
			}
			outputStream.close();
			inputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static boolean isExist(String path) {
		if (path == null || path.trim().length() == 0) {
			return false;
		}
		File file = new File(path);
		return file.exists();
	}

	public static long getFileSizes(File f) {
		long s = 0;
		if (f.exists()) {
			FileInputStream fis = null;
			try {
				fis = new FileInputStream(f);
				s = fis.available();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return s;
	}

	/**
	 * 列举文件列表
	 * @param base 根目录
	 * @param path 路径
	 * @param type 文件类型
	 * 0： 目录  1： 文件 -1: 不过滤
	 * @return 返回文件列表
	 */
	public static List<UIFile> list(String base, String path) {
		if (path != null && path.trim().length() == 0) {
			return null;
		}
		File file = new File(path);
		if (!file.exists() || !file.isDirectory()) {
			return null;
		}
		File files[] = file.listFiles();
		if (files.length == 0) {
			return null;
		}
		String basePath = path.substring(base.length());

		List<UIFile> uiFiles = new ArrayList<UIFile>();
		for (File f : files) {
			if(f.isDirectory()){
				continue;
			}
			UIFile uiFile = new UIFile();
			uiFile.setName(f.getName());
			uiFile.setType(1);
			uiFile.setSize(getFileSizes(f));
			uiFile.setPath(basePath + File.separator + f.getName()); 
			uiFiles.add(uiFile);
		}
		files = null;
		return uiFiles;
	}

	public static void download(String path, String filename,
			HttpServletResponse response) {
		String ext = StringUtils.getFilenameExtension(filename);
		if (ext == null) {
			return;
		}
		if (contentTypes.containsKey(ext)) {
			response.setContentType(contentTypes.get(ext));
		} else {
			return;
		}

		try {
			response.setCharacterEncoding("UTF-8");
			response.setHeader("Content-Disposition", "attachment;filename="
					+ java.net.URLEncoder.encode(filename, "UTF-8"));
			File file = new File(path);
			if (file.exists()) {
				InputStream ips = null;
				OutputStream ops = null;

				try {
					ips = new FileInputStream(file);
					ops = response.getOutputStream();
					byte[] b = new byte[1024];
					int len = 0;
					while ((len = ips.read(b)) != -1) {
						ops.write(b, 0, len);
					}
				} finally {
					if (ips != null) {
						try {
							ips.close();
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
					if (ops != null) {
						try {
							ops.close();
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	public static void createFolder(String path) {
		File file = new File(path);
		if (!file.exists()) {
			file.mkdirs();
		}
	}

	public static boolean deleteFolder(String path) {
		File file = new File(path);
		if (file.exists()) {
			return deleteFile(file);
		}
		return false;
	}

	public static boolean deleteFile(File file) {
		if (file.exists()) {
			if (file.isFile()) {
				System.gc();
				return file.delete();
			} else if (file.isDirectory()) {
				File[] files = file.listFiles();
				for (int i = 0; i < files.length; i++) {
					if (!deleteFile(files[i]))
						return false;
				}
				return file.delete();
			} else
				return false;
		}
		return false;
	}

	public static boolean delete(String path) {
		return deleteFile(new File(path));
	}

	public static boolean mkdir(String path) {
		try {
			File file = new File(path);
			if (!file.exists()) {
				file.mkdirs();
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static void copy(String sourceDir, String targetDir) {
		File targetFile = new File(targetDir);
		if(targetFile.isDirectory()){
			targetFile.mkdirs();
		}
		File tmpFile = new File(sourceDir);
		if(tmpFile.isDirectory()){
			File[] file = tmpFile.listFiles();
			for (int i = 0; i < file.length; i++) {
				if (file[i].isFile()) {
					File sourceFile = file[i];
					copyFile(sourceFile, new File(
							new File(targetDir).getAbsolutePath() + File.separator
							+ file[i].getName()));
				}
				if (file[i].isDirectory()) {
					String source = sourceDir + "/" + file[i].getName();
					String target = targetDir + "/" + file[i].getName();
					copy(source, target);
				}
			}
		}
		else{
			copyFile(tmpFile, targetFile);
		}
		
	}
}
